<!DOCTYPE html>
<html>
<head>
    <title>Electromagnetic Field Diagram</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #fff;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="450" height="400"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // Style settings
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 2;
        ctx.font = 'italic 18px serif';

        // --- Projection Parameters ---
        const origin = { x: 180, y: 280 };
        const a = 100; // x-dimension on screen
        const b = 100; // y-dimension on screen
        const c = 130; // z-dimension on screen

        const x_vec = { x: 1, y: 0.15 };
        const y_vec = { x: 0.7, y: -0.4 };

        // --- Helper function to draw an arrow ---
        function drawArrow(fromX, fromY, toX, toY, headLength = 8) {
            const dx = toX - fromX;
            const dy = toY - fromY;
            const angle = Math.atan2(dy, dx);
            ctx.moveTo(fromX, fromY);
            ctx.lineTo(toX, toY);
            ctx.lineTo(toX - headLength * Math.cos(angle - Math.PI / 6), toY - headLength * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - headLength * Math.cos(angle + Math.PI / 6), toY - headLength * Math.sin(angle + Math.PI / 6));
        }
        
        // --- Calculate 3D vertex positions in 2D space ---
        const V = {};
        V.p000 = { x: origin.x, y: origin.y };
        V.p100 = { x: origin.x + a * x_vec.x, y: origin.y + a * x_vec.y };
        V.p010 = { x: origin.x + b * y_vec.x, y: origin.y + b * y_vec.y };
        V.p110 = { x: V.p100.x + b * y_vec.x, y: V.p100.y + b * y_vec.y };

        V.p001 = { x: V.p000.x, y: V.p000.y - c };
        V.p101 = { x: V.p100.x, y: V.p100.y - c };
        V.p011 = { x: V.p010.x, y: V.p010.y - c };
        V.p111 = { x: V.p110.x, y: V.p110.y - c };
        
        // --- Draw the base plane (φ=0) ---
        ctx.beginPath();
        ctx.moveTo(V.p000.x - 70, V.p000.y - 15);
        ctx.lineTo(V.p100.x + 40, V.p100.y + 15);
        ctx.lineTo(V.p110.x + 40, V.p110.y - 25);
        ctx.lineTo(V.p010.x - 70, V.p010.y - 55);
        ctx.closePath();
        ctx.stroke();

        // --- Draw the block ---
        // Dashed lines
        ctx.beginPath();
        ctx.setLineDash([5, 5]);
        ctx.moveTo(V.p000.x, V.p000.y);
        ctx.lineTo(V.p100.x, V.p100.y);
        ctx.moveTo(V.p000.x, V.p000.y);
        ctx.lineTo(V.p010.x, V.p010.y);
        ctx.moveTo(V.p010.x, V.p010.y);
        ctx.lineTo(V.p110.x, V.p110.y);
        ctx.stroke();
        
        // Solid lines
        ctx.beginPath();
        ctx.setLineDash([]);
        // Vertical edges
        ctx.moveTo(V.p000.x, V.p000.y);
        ctx.lineTo(V.p001.x, V.p001.y);
        ctx.moveTo(V.p010.x, V.p010.y);
        ctx.lineTo(V.p011.x, V.p011.y);
        ctx.moveTo(V.p100.x, V.p100.y);
        ctx.lineTo(V.p101.x, V.p101.y);
        ctx.moveTo(V.p110.x, V.p110.y);
        ctx.lineTo(V.p111.x, V.p111.y);
        // Top face
        ctx.moveTo(V.p001.x, V.p001.y);
        ctx.lineTo(V.p101.x, V.p101.y);
        ctx.lineTo(V.p111.x, V.p111.y);
        ctx.lineTo(V.p011.x, V.p011.y);
        ctx.closePath();
        ctx.stroke();
        
        // --- Draw Coordinate Axes ---
        ctx.beginPath();
        ctx.setLineDash([5, 5]);
        // Z-axis (part below plane)
        ctx.moveTo(origin.x, origin.y + 20);
        ctx.lineTo(origin.x, origin.y);
        // Y-axis
        drawArrow(origin.x, origin.y, origin.x + 1.3 * b * y_vec.x, origin.y + 1.3 * b * y_vec.y);
        // X-axis
        drawArrow(origin.x, origin.y, origin.x + 1.3 * a * x_vec.x, origin.y + 1.3 * a * x_vec.y);
        ctx.stroke();
        // Z-axis (solid part with arrow)
        ctx.beginPath();
        ctx.setLineDash([]);
        drawArrow(origin.x, origin.y, origin.x, origin.y - c - 30);
        ctx.stroke();
        
        // --- Draw Current Source (J) ---
        const top_center = {
            x: (V.p001.x + V.p111.x) / 2,
            y: (V.p001.y + V.p111.y) / 2,
        };
        ctx.beginPath();
        ctx.arc(top_center.x, top_center.y, 3, 0, 2 * Math.PI);
        ctx.fill();
        ctx.beginPath();
        drawArrow(top_center.x + 30, top_center.y - 30, top_center.x + 3, top_center.y - 3);
        ctx.stroke();

        // --- Add Labels ---
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        
        // Axis labels
        ctx.fillText('z', origin.x - 15, origin.y - c - 30);
        ctx.fillText('y', origin.x + 1.3 * b * y_vec.x + 10, origin.y + 1.3 * b * y_vec.y - 10);
        ctx.fillText('x', origin.x + 1.3 * a * x_vec.x + 10, origin.y + 1.3 * a * x_vec.y + 10);
        
        // Dimension labels
        ctx.fillText('c', V.p000.x - 12, V.p000.y - c / 2);
        ctx.fillText('a', V.p010.x - 15, V.p010.y + 5);
        ctx.fillText('b', (V.p100.x + V.p110.x) / 2, V.p100.y + 20);
        
        // Potential label
        ctx.fillText('φ = 0', origin.x - 80, origin.y - 10);

        // Current label
        ctx.fillText('J', top_center.x + 40, top_center.y - 40);

        // Figure caption
        ctx.font = 'bold 16px sans-serif';
        ctx.fillText('Fig. 2.68', canvas.width / 2, canvas.height - 20);
    </script>
</body>
</html>